#include <stdio.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <mntent.h>
#include <sys/stat.h>
#include <unistd.h>

#define DEV_PATH "/dev/inode_query"
#define IOCTL_CMD 0xDEADBEEF

struct query_request {
    char mount_root[256];
    unsigned long inode;
    char result[2048];
};

// 通过设备路径获取挂载点
char* get_mountpoint(const char* device_path) {
    struct stat device_stat;
    struct mntent *ent;
    FILE *fp;

    // 获取设备的主次设备号
    if (stat(device_path, &device_stat) != 0) {
        perror("stat failed");
        return NULL;
    }

    // 打开挂载信息文件
    if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
        perror("setmntent failed");
        return NULL;
    }

    // 遍历所有挂载点
    while ((ent = getmntent(fp)) != NULL) {
        struct stat mnt_stat;
        
        // 获取挂载设备的属性
        if (stat(ent->mnt_fsname, &mnt_stat) != 0) {
            continue;  // 跳过无效条目
        }

        // 比较设备号（主设备号+次设备号）
        if (mnt_stat.st_rdev == device_stat.st_rdev) {
            endmntent(fp);
            return strdup(ent->mnt_dir);  // 返回挂载点目录
        }
    }

    endmntent(fp);
    return NULL;
}

int main() {
    int fd = open(DEV_PATH, O_RDWR);
    if (fd < 0) {
        perror("打开设备失败");
        return -1;
    }

    struct query_request req;
    printf("输入设备路径 (如 /dev/sda1): ");
    char device_path[256];
    scanf("%255s", device_path);
    char *mount_point = get_mountpoint(device_path);
    if (!mount_point) {
        perror("获取挂载点失败");
        close(fd);
        return -1;
    }
    printf("挂载点: %s\n", mount_point);
    int fd2 = open(mount_point, O_RDONLY);
    if (fd < 0) {
	    perror("打开挂载路径失败");
	    return -1;
    }
    memcpy(&req.mount_root, mount_point, 256);

    printf("输入 inode 号: ");
    scanf("%lu", &req.inode);

    printf("挂载点: %s\n", mount_point);

    if (ioctl(fd, IOCTL_CMD, &req) < 0) {
        perror("ioctl 失败");
        close(fd);
	close(fd2);
        free(mount_point);
        return -1;
    }

    printf("路径: %s\n", req.result);
    close(fd);
    close(fd2);
    free(mount_point);
    return 0;
}

